/*
 * Galaxium Messenger
 * 
 * Copyright (C) 2008 Paul Burton <paulburton89@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Collections.Generic;
using System.Text;

using Anculus.Core;

using Galaxium.Core;

namespace Galaxium.Protocol.Msn
{
	public abstract class AbstractMsnContent : IMsnContent
	{
		MsnContentAttribute _contentAttr;
		byte[] _data;
		Encoding _encoding = Encoding.UTF8;
		MIMECollection _mimeHeader = new MIMECollection ();
		bool _sendEncoding = false;
		MsnSession _session;
		IMsnEntity _source;
		
		protected MsnContentAttribute ContentAttribute
		{
			get { return _contentAttr; }
		}
		
		public string ContentType
		{
			get { return ContentAttribute.ContentTypes[0]; }
		}
		
		public virtual byte[] Data
		{
			get { return _data; }
			set
			{
				_data = value;
				OnDataChanged ();
			}
		}
		
		public string DataString
		{
			get { return _encoding.GetString (Data); }
			set { Data = _encoding.GetBytes (value); }
		}
		
		public Encoding Encoding
		{
			get { return _encoding; }
			set { _encoding = value; }
		}
		
		public MIMECollection MIMEHeader
		{
			get { return _mimeHeader; }
			set { _mimeHeader = value; }
		}
		
		public bool SendEncoding
		{
			get { return _sendEncoding; }
			set { _sendEncoding = value; }
		}
		
		public MsnSession Session
		{
			get { return _session; }
		}
		
		public IMsnEntity Source
		{
			get { return _source; }
			protected set { _source = value; }
		}
		
		AbstractMsnContent ()
		{
			foreach (MsnContentAttribute att in this.GetType ().GetCustomAttributes (typeof (MsnContentAttribute), false))
				_contentAttr = att;
		}
		
		public AbstractMsnContent (MsnSession session)
			: this ()
		{
			_session = session;
			_source = session.Account;
		}
		
		public AbstractMsnContent (ContentCommand cmd)
			: this ()
		{
			ReadCommand (cmd);
		}
		
		public virtual T ToCommand<T> () where T : ContentCommand
		{
			T cmd = (T)Activator.CreateInstance (typeof (T), _session);
			WriteCommand (cmd);
			return cmd;
		}
		
		protected virtual void ReadCommand (ContentCommand cmd)
		{
			_session = cmd.Session;
			_data = cmd.Payload;
			_sendEncoding = cmd.MIMEHeader["Content-Type"].HasAttribute ("charset");
			
			foreach (KeyValuePair<string, MIMEValue> pair in cmd.MIMEHeader)
				_mimeHeader[pair.Key] = pair.Value.ToString ();
			
			if (cmd is MSGCommand)
				_source = ((MSGCommand)cmd).Source;
			else if (cmd is UBMCommand)
				_source = ((UBMCommand)cmd).Source;
			else
				_source = _session.Account;
			
			if (_sendEncoding)
			{
				try
				{
					_encoding = Encoding.GetEncoding (cmd.MIMEHeader["Content-Type"]["charset"]);
				}
				catch (ArgumentException)
				{
					Log.Warn ("Unknown text encoding '{0}', falling back to UTF8", cmd.MIMEHeader["Content-Type"]["charset"]);
					_encoding = Encoding.UTF8;
				}
			}
		}
		
		protected virtual void WriteCommand (ContentCommand cmd)
		{
			cmd.ContentType = ContentType;
			
			foreach (KeyValuePair<string, MIMEValue> pair in _mimeHeader)
				cmd.MIMEHeader[pair.Key] = pair.Value.ToString ();
			
			cmd.Payload = _data;
			
			//TODO: will this always send the encoding name correctly?
			if (_sendEncoding)
				cmd.MIMEHeader["Content-Type"][" charset"] = _encoding.HeaderName.ToUpperInvariant ();
		}
		
		protected virtual void OnDataChanged ()
		{
			
		}
	}
}
